using System;
using System.Text;
using T.FAS.Runtime.Base.Common;
using T.FAS.Runtime.Base.Entity;
using T.FAS.Runtime.Base.Service;
using T.FAS.Runtime.Metadata.Entity.DataModel;

namespace T.FAS.Runtime.DataAccess.Engine
{
    /// <summary>
    /// 掩码工具类
    /// </summary>
    public sealed class MaskTool
    {
        private static readonly string s_defualtMaskData = null;
        private static readonly int s_defaultMaskLength = 6;
        private static readonly char s_defaultMaskChar = '*';
        /// <summary>
        /// 掩码特殊占位符，出现在CNO.Element.ID中标识这个Element元素为动态掩码元素
        /// </summary>
        private const string maskSpecialChars = "_$mask_";

        private MaskTool() { }

        public static MaskSetting GetMaskSetting(string maskId)
        {
            if (string.IsNullOrEmpty(maskId)) return null;
            return FasMaskService.GetInstance().GetMaskSetting(maskId);
        }

        /// <summary>
        /// 计算掩码值进行存储
        /// </summary>
        /// <param name="rule"></param>
        /// <param name="input"></param>
        /// <returns></returns>
        public static string CalculateMaskData(MaskingRule rule, string input)
        {
            if (!rule.IsEnable) return s_defualtMaskData;
            //如果为全掩码模式，则返回定长的掩码
            if (!rule.IsPartialMasking)
            {
                char maskingCharacter = rule.MaskingCharacter == ' ' ? s_defaultMaskChar : rule.MaskingCharacter;
                return new StringBuilder(s_defaultMaskLength).Insert(0, maskingCharacter.ToString(), s_defaultMaskLength).ToString();
            }

            //系统规则直接对接sys SDK
            if (rule.MaskingType == MaskingType.System)
            {
                throw new Exception();
            }
            //走低代码的自定义规则
            else
            {
                //如果为部分掩码，则需要获取掩码设置，进行掩码计算
                MaskSetting mask = GetMaskSetting(rule.RuleID);
                string pattern, replacement;
                if (mask == null)
                {
                    if (!string.IsNullOrEmpty(rule.RegPattern) && !string.IsNullOrEmpty(rule.Replacement))
                    {
                        pattern = rule.RegPattern;
                        replacement = rule.Replacement;
                    }
                    else
                        return s_defualtMaskData;
                }
                else
                {
                    pattern = mask.RegPattern;
                    replacement = mask.Replacement;
                }
                //todo:改为调用sys SDK
                if (FasMaskService.GetInstance().TryGetMaskData(pattern, replacement, input, out string result))
                {
                    return result;
                }
                else
                {
                    //获取掩码规则失败，todo:异常处理还是
                    return s_defualtMaskData;
                }
            }
        }

        /// <summary>
        /// 获取掩码列的元素对应的DataItem id 例如 {ele.ID}_$mask_{column.ColumnName:Code_mask}
        /// </summary>
        /// <param name="dataObject"></param>
        /// <param name="ele"></param>
        /// <returns></returns>
        /// <exception cref="Exception"></exception>
        public static string GetMaskDataItemElementIDKey(DataObject dataObject, CompositeNodeObjectElement ele)
        {
            var realFieldName = DataColumn.GetMaskColumnName(dataObject, ele.DataColumn.ColumnName);
            if (string.IsNullOrEmpty(realFieldName))
                throw new Exception($"cdo:{ele.CompositeDataObjectID}，ele:{ele.Alias} failed to get masking field name");
            return $"{ele.ID}{maskSpecialChars}{realFieldName}";
        }

        /// <summary>
        /// 获取掩码列对应的物理存储列名 例如 {column.ColumnName:Code_mask}
        /// </summary>
        /// <param name="dataItemKey"></param>
        /// <param name="realFieldName"></param>
        /// <param name="elementid"></param>
        /// <returns></returns>
        public static bool IsMaskDataItemElementIDKey(string dataItemKey, out string realFieldName, out string elementid)
        {
            elementid = dataItemKey;
            realFieldName = null;
            int ind = dataItemKey.IndexOf(maskSpecialChars);
            if (ind > 0)
            {
                realFieldName = dataItemKey.Substring(ind + 7); //7 == len(_$mask_)
                elementid = dataItemKey.Substring(0, ind);
                return true;
            }
            return false;
        }

        public static bool EnableFASMaskStorage(MaskingRule maskingRule)
        {
            return maskingRule.IsEnable && ConfigUtil.Instance.EnableFASMaskStorage;
        }
    }
}
